<?php
/**
 * Created by PhpStorm.
 * User: peiyu
 * Date: 2019/7/3
 * Time: 14:46
 */

namespace app\common\model;

use think\Validate;
use think\Model;


class config extends Model
{
    public static function canInsertColumns(array $dimensions){

        $columns= array_keys($dimensions);
        $columns=array_merge($columns,['key', 'value', 'value_type', 'rem', 'status']);
        return $columns;
    }
    public static function canUpdateColumns(array $dimensions){

        $columns= array_keys($dimensions);
        $columns=array_merge($columns,[ 'value', 'value_type', 'rem', 'status']);
        return $columns;
    }
    public static function getConfigByKey($key)
    {

        if (!$key) throw new \Exception("key can not is null");
        $catch_key = config("my.catchKEY.configByKey") . $key;
        $_v = cache($catch_key);
        if ($_v) return $_v;
        $conf = self::where("key", $key)->where("status", "0")->select()->toArray();
        if ($conf) cache($catch_key, $conf, 3600);
        return $conf;
    }

    private static function valueTypeCheck($value,$value_type){
        if($value_type=="string" && !$value)return true;
        if(!$value)return false;
        switch ($value_type){
            case "array":
                $_values = json_decode($value);
                if ($_values === NULL || !is_array($_values)) {
                    throw new \Exception("值格式不正确，必须是数组json格式");
                }
                return true;
                break;
            case "int":
                return Validate ::make()
                    ->rule('v', 'integer')
                    ->check(["v"=>$value]);
                break;
                break;
            case "float":
                return Validate ::make()
                    ->rule('v', 'float')
                    ->check(["v"=>$value]);
                break;
                break;
            case "json":
                return json_decode($value)!==NULL;
                break;
        }
        return true;
    }

    public static function updateConfig(array $data,array $dimensions)
    {

        if(!self::valueTypeCheck(array_get($data, "value"),array_get($data, "value_type")))throw new \Exception("值和值类型不匹配") ;

        $id = array_get($data, "id");
        if (!$id) throw new \Exception("id can not is null");


        $v = array_get($data, "value");

        ///清除旧的关联关系
        $_old=self::where("id", $id)->find();
        $key=$_old->key;
        if($_old->value!==$v &&  $_old->value)self::deleteKeyDepend($_old->value,$key);

        self::where("id", $id)->update( array_only_key( $data , self::canUpdateColumns($dimensions) ));

        ////  创建新的关联关系  我和我的上游的依赖
        if($_old->value!==$v && $v)self::createKeyDepend($v, $key);
        self::clearCache($key);
    }

    private static function exitCheck(array $data,array $dimensions){
        $db= self::where("key", $data["key"]);
        foreach ($dimensions as $dim=>$v){
            $db=$db->where($dim, array_get($data,$dim,'') );
        }
        return $db->count();
    }

    private static function dimensionValueCheck(array $data,array $dimensionList){

        foreach ($dimensionList as $item){
            if( array_get($item,"if_free") ==1 )continue;
            $key=array_get($item,"key") ;
            $v=array_get($data,$key,"") ;
            $_vs=array_get($item,"values_array",[]);
            if( !in_array($v,  $_vs ) )throw new \Exception($v." not in ".  implode($_vs) );
        }
    }

    public static function insertConfig(array $data,array $dimensions,array $dimensionList)
    {
        $key = array_get($data, "key");
        if (!$key) throw new \Exception("key can not is null");
        if(!self::valueTypeCheck(array_get($data, "value"),array_get($data, "value_type")))throw new \Exception("值和值类型不匹配") ;

        if(self::exitCheck($data,$dimensions))throw new \Exception("已存在不能重复！");

        self::dimensionValueCheck($data,$dimensionList);

        self::create( array_only_key( $data , self::canInsertColumns($dimensions) ) );

        ////  创建新的关联关系  我和我的上游的依赖
        $v = array_get($data, "value");
        if($v)self::createKeyDepend($v, $key);
        self::clearCache($key);
    }

    public static function delConfig($id){
        if (!$id) throw new \Exception("id can not is null");

        $_c=self::where("id", $id)->find();

        ///如果有下游依赖，禁止删除
        $_down= keydepend::getMyDownDepend($_c->key);
        if($_down)throw new \Exception("haveDownDepend");

        self::where("id", $id)->delete();

        ///清除关联关系
        if($_c->value)self::deleteKeyDepend($_c->value,$_c->key);
        self::clearCache($_c->key);
    }

    //创建依赖： 我和我的上游的依赖
    private static function createKeyDepend($configValue,$key){

        $vars = getVarFromContent($configValue);
        if(!$vars)return ;
        foreach ($vars as $var){
            $_c=self::where("key", $var)->where("status", "0")->find();
            if(!$_c)continue;
            keydepend::addDepend($var,$key);
        }

    }
    //删除依赖： 我和我的上游的依赖
    private static function deleteKeyDepend($configValue,$key){

        $vars = getVarFromContent($configValue);
        if(!$vars)return ;
        foreach ($vars as $var){
            keydepend::delDepend($var,$key);
        }

    }

    private static function clearCache($key){
        $catch_key = config("my.catchKEY.configByKey") . $key;
        cache($catch_key, null);
    }


    /// 查出不存在的维度，以便创建
    public static function checkDimension(array $dimensions)
    {
        $ret = [];
        $columnNames=self::getColumnNames();
        if (!$columnNames) throw new \Exception("checkDimension fail");

        foreach ($dimensions as $value) {
            if (! in_array($value, $columnNames)) $ret[] = $value;
        }
        return $ret;
    }

    public static function getColumnNames(){

        return getcolumns( self::getTable() );


    }

    public static function  total(array $params){


        $columnNames=self::getColumnNames();
        $wheres=array_only_key($params,$columnNames) ;
        /*foreach ($params as $key=>$value ){
            if( in_array($key,$columnNames) && $value){
                $wheres[$key]=$value;
            }
        }*/

        $db= self::where("id",">",0);
        if($wheres){
            foreach ($wheres as $key=>$value){
                $db=$db->where($key,$value);
            }
        }
        $db=$db->order("key","asc");

        return $db->count();
    }

    public static function selectConfig(array $params,array $dimensions){


        $page=array_get($params,"page",1);

        $columnNames=self::getColumnNames();
        $wheres= array_filter( array_only_key($params,$columnNames)) ;


        $db= self::page($page,100);
        if($wheres){
            foreach ($wheres as $key=>$value){
                $db=$db->where($key,$value);
            }
        }
        $db=$db->order("key","asc");
         foreach ($dimensions as $di=>$v){
             $db->order($di,"asc");
         }
        $list= $db->select()->toArray();
         foreach ($list as &$item){
             $_now=time();
             if(date("Y-m-d", strtotime($item['looktime']) ) != date("Y-m-d",$_now)){
                 $item['lookcount']=0;
             }

         }
         return $list;
    }

    public static function  distinctConfig(array $columns){
        $ret=[];
        foreach ($columns as $column){
            $ret[$column] = self::field(" `".$column."`,count(*) as count")
                ->group($column)->where($column,'<>','')  ->select()->toArray();
        }
        return $ret;
    }

    public static function setLook(array $data){

        $id=$data["id"];

        $cof=self::where("id", $id)->find();
        $_now=time();
        if(date("Y-m-d", strtotime($cof->looktime) ) == date("Y-m-d",$_now)){
            self::where("id", $id)->inc('lookcount')->update(["looktime"=>date('Y-m-d H:i:s', $_now)]);
        }else{
            self::where("id", $id)->update(["looktime"=>date('Y-m-d H:i:s', $_now) ,"lookcount"=>1]);
        }

    }

}